<%= stylesheet_link_tag '/stylesheets/blue/style' %>
<style>
.c {
	text-align: center;
}
.statusBar {
	margin: 10px -10px;
	padding: 5px 10px;
	font-size: 12pt;
	background-color: #fff;
	border: 1px solid #bbc;

}
td {
	padding: 6px 10px;
}
table {
	border-collapse: collapse;
	margin: 4px;
}
table td {
	border: 1px solid #bbc;
}
#current, #library {
	width: 100%;
}
#current th:last-child, #library th:last-child {
	width: 10em;
}
#current td:first-child img, #library td:first-child img {
	border: none;
}
#ellipsis {
	margin-left: 4px;
	position: absolute;
}
.thumb {
	width: 10px;
}
.status {
	width: 8em;
}	
#library .status {
	cursor: pointer;
}
.size {
	width: 10em;
}
#statusMenu {
	position: absolute;
	list-style-type: none;
	background-color: #fff;
	padding: 0;
	margin: 0;
	border: 1px solid black;
}
#statusMenu li {
	padding: 4px 20px 4px 10px;
	color: gray;
}
#statusMenu li.menu {
	color: black;
}
#statusMenu li.menu:hover {
	color: #fff;
	background-color: blue;
	cursor: pointer;
}
#toggle {
	width: 80px;
	float: right;
	margin-top: 1px;
}
img[onclick] {
	cursor: pointer;
	vertical-align: middle;
}
#serverStatus a {
	font-size: 11pt;
}
</style>
<%= javascript_include_tag 'jquery', 'jquery.tablesorter.min' %>
<script type='text/javascript'>//<![CDATA[
var gStatus			= <%= @serverStatus.to_json %>;
var gDecay			= -1;
var gIntervalId		= null;

var FORMAT_BYTES_RE = /^(\d+)(\d{3})/;
var POS;
var STATUS_MAP		= {
	sleeping: 'sleeping.&nbsp;&nbsp;<a href="javascript:void(checkQueue())">Check Instant Queue</a>',
};

$(function() {
	POS = getXY($('#content')[0]);

	$('#library').tablesorter({
		headers: {0: {sorter: false}},
		sortList: [[<%= %w(. Title Status Size).index(@orderCol) %>, <%= %w(ASC DESC).index(@orderDir) %>]],
		widgets: ['zebra']
	}).bind('sortEnd', function() {
		var $th = $('.headerSortUp, .headerSortDown', this);
		setCookie('order', $th.html() + ' ' + ($th.hasClass('headerSortUp') ? 'DESC' : 'ASC'));
	});

	initMenu();
	onStatusChange(gStatus);
	updateTick(true);
});

function setCookie(name, value, expire) {
	if (!expire) {
		expire = new Date();
	    expire.setDate(expire.getDate() + 365);
	}

    document.cookie = name + '=' + escape(value) + ';expires=' + expire.toGMTString();
}

function getXY(e) {
	var result = {x: 0, y: 0};

	while (e) {
		result.x += e.offsetLeft;
		result.y += e.offsetTop;
		e = e.offsetParent;
	}

	return result;
}

function initMenu() {
	$('#library tbody .status').click(function(e) {
		var status = $(this).html();

		$('#statusMenu li').each(function(i, li) {
			var $li = $(li);
			switch ($li.html()) {
			case 'Delete':
				if (status != 'deleted')
					$li.addClass('menu');
				else
					$li.removeClass('menu');
				break;
			case 'Retry':
				if (status == 'error' || status == 'deleted')
					$li.addClass('menu');
				else
					$li.removeClass('menu');
				break;
			}
		});

		$('#statusMenu').
			attr('current', $(e.target.parentNode).attr('id')).
			css({
				top: e.pageY - POS.y - 10 + 'px',
				left: e.pageX - POS.x + 50 + 'px'
			}).
			show();

		return false;
	});

	function clearMenu() { $('#statusMenu').attr('current', '').hide(); }

	$(document).click(clearMenu);
	$(document).keydown(function(e) {
		if (e.keyCode == 27) {
			clearMenu();
			return false;
		}

		return true;
	});

	$('#statusMenu').click(function(e) {
		var $e = $(e.target);
		if (!$e.hasClass('menu')) return;
		var cmd = $e.text();

		var trId = $('#statusMenu').attr('current');
		var nfId = trId.substr(2);
		var row = $('#' + trId);
		var odd = row.hasClass('odd');
		var title = row.find('td.title a').html();

		switch (cmd) {
		case 'Delete':
			if (confirm('Really delete "' + title + '"?')) {
				$.get('/videos/delete_video/' + nfId, {}, function(data) {
					row.replaceWith(data);
					row.addClass(odd ? 'odd' : 'even');
					checkQueue();
				});
			}
			break;

		case 'Retry':
			$.get('/videos/retry_video/' + nfId, {}, function(data) {
				restripe($('#current tbody').prepend(data));
				restripe($('#library tbody'));
			});
			break;
		}
	});
}

//
// Start ticker with updateTick(true), stop with stopTick(true).
//
// Ticker runs whenever server status is not "stopped"
//

function updateTick(changed) {
	if (changed) {
		if (gDecay == 0) return;

		gDecay = 0;
	}
	else {
		++gDecay;

		if (gDecay > 5) {
			gDecay = 5;
			return;
		}
	}

	// If there's already a timer running
	stopTick();

	// No interval was set yet or it was just cleared
	gIntervalId = setInterval(tick, 300 * Math.pow(2, gDecay));
}

function stopTick(resetDecay) {
	if (gIntervalId) {
		clearInterval(gIntervalId);
		gIntervalId = null;
	}

	if (resetDecay) {
		gDecay = -1;
		$('#ellipsis').html('');
	} 
}

function tick() {
	var e = $('#ellipsis');
	var s = e.html();

	if (s.length == 4) {
		$.getJSON('/videos/status', {}, function(data) {
			var changed = false;

			var newStatus = data[0];

			// Special handling while starting
			if ($('#toggle').val() == 'Starting...' && /not running/.test(newStatus)) {
				var m = /^starting(\.*)$/.exec(gStatus);

				if (m && m[1].length < 5) {
					// Keep waiting
					newStatus = gStatus + '.';
					onStatusChange(newStatus);
				}
			}

			if (gStatus != newStatus) {
				onStatusChange(newStatus);
				changed = true;
			}

			if (gStatus == 'stopped')
				stopTick(true);
			else
				updateTick(changed);

			// Update videos
			var updatedIds = {};

			var sizes = data[1];
			for (var i = 0; i < sizes.length; ++i) {
				var nfId = sizes[i][0];
				var trId = 'r-' + nfId;
				var size = sizes[i][1];

				updatedIds[trId] = 1;

				var eSize = $('#' + trId + ' td:last');

				if (eSize.length) {
					if (eSize.html() != size) {
						eSize.html(size);
						changed = true;
					}
				}
				else {
					// New video
					$.get('/videos/video/' + nfId, {}, function(data) {
						restripe($('#current tbody').prepend(data));
					});
				}
			}

			// Check for any videos no longer returning status
			var toGet = [];

			$('#current tbody tr').each(function(i, tr) {
				var $tr = $(tr);
				var trId = $tr.attr('id');

				if (!updatedIds[trId]) {
					toGet.push(trId.substr(2));
					$tr.remove();
				}
			});

			if (toGet.length) {
				$.get('/videos/video/' + toGet.join(','), {}, function(data) {
					restripe($('#library tbody').prepend(data));
				});

				changed = true;
			}
		});

		e.html('.');
	}
	else e.html(s + '.');
}

function restripe($t) {
	$t.find('tr').each(function(i, tr) {
		$(tr).removeClass('odd even').addClass(i & 1 ? 'odd' : 'even');
	});
}

function onStatusChange(newStatus) {
	var e = $('#serverStatus');
	var label = 'Stop';
	var color = 'orange';

	if (/not running|stopped/.test(newStatus)) {
		label = 'Start';
		color = 'red';
	}
	else if (/starting/.test(newStatus)) {
		label = 'Starting...';
	}
	else if (newStatus == 'OK')
		color = 'green';

	$('#toggle').val(label).attr('disabled', label == 'Starting...');
	e.css('color', color);

	gStatus = newStatus;

	e.html(STATUS_MAP[gStatus] ? STATUS_MAP[gStatus] : gStatus);
}

function refresh() {
	$('#ellipsis').html('');
	updateTick(true);
}

function toggle() {
	$('#toggle').val() == 'Start'
		? startup()
		: shutdown();
}

function startup() {
	onStatusChange('starting..');
	updateTick(true);
	$.get('/videos/server_start', {}, refresh);
}

function shutdown() {
	$('#toggle').val('Stopping...').attr('disabled', 1);
	$.get('/videos/server_shutdown', {}, refresh);
}

function checkQueue() {
	$.get('/videos/server_check', {}, refresh);
}

function formatStatus(s) {
	return STATUS_MAP[s] ? STATUS_MAP[s] : s;
}

function formatBytes(s) {
	s = parseInt(s) / 1024.0
	var units = ' KB'

	if (s > 1024) {
		s /= 1024.0;
		units = ' MB';
	}

	while (FORMAT_BYTES_RE.test(s)) s.replace(FORMAT_BYTES_RE, '$1,$2');

	return s + units;
}
//]]>
</script>

<div class='box'>
	<div class='statusBar'>
		<b style='float: left'>Downloader Status:&nbsp;</b>
		<img src='/images/action_refresh.gif' onclick='refresh()' style='float: left; margin: 2px 3px' />
		<span id='serverStatus' style='float: left'></span>

		<%= button_to_function('Start', 'toggle()', {:id => 'toggle'}) %>
		<div style='clear: both'></div>
	</div>

	<table id='current' class='tablesorter'>
		<thead>
			<tr>
				<th>&nbsp;</th>
				<th>Title</th>
				<th>Status</th>
				<th>Progress <span id='ellipsis'></span></th>
			</tr>
		</thead>
		<tbody>
		<%
			@videos.each {|v|
				next if v.status_id != VideoStatus::DOWNLOADING
		%>
				<%= render({
					:partial	=> 'video',
					:object		=> v,
					:locals		=> {
						:showThumbs 	=> @showThumbs,
						:imgUrl			=> @imgUrl,
						:statusLabels	=> @statusLabels
					}
				}) %>
		<%
			}
		%>
		</tbody>
	</table>

	<hr />

	<h2>Library</h2>
	<table id='library' class='tablesorter'>
		<thead>
			<tr>
				<%
					orderCol, orderDir = @order.split(' ')
					val = 'headerSort' + (orderDir == 'ASC' ? 'Down' : 'Up')

					clsTitle = clsStatus = clsSize = ''

					case orderCol
						when 'Title'	then clsTitle = val
						when 'Status'	then clsStatus = val
						when 'Size'		then clsSize = val
					end
				%>
				<th class='thumb'>&nbsp;</th>
				<th class='header title <%= clsTitle %>'>Title</th>
				<th class='header status <%= clsStatus %>'>Status</th>
				<th class='header size <%= clsSize %>'>Size</th>
			</tr>
		</thead>
		<tbody>
		<%
			@videos.each {|v|
				next if v.status_id == VideoStatus::DOWNLOADING
		%>
				<%= render({
					:partial	=> 'video',
					:object		=> v,
					:locals		=> {
						:showThumbs 	=> @showThumbs,
						:imgUrl			=> @imgUrl,
						:statusLabels	=> @statusLabels
					}
				}) %>
		<%
			}
		%>
		</tbody>
	</table>
</div>

<p>&nbsp;</p>

<ul id='statusMenu' style='display: none'>
	<li>Delete</li>
	<li>Retry</li>
</ul>
